package com.ld.zookeeper.api;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * @author:ld
 * @create:2020-04-21 14:01
 * @description:
 */
public class ZookeeperGet {

    //连接对象
    private ZooKeeper zooKeeper;

    //连接地址
    private final String IP = "127.0.0.1:2181";

    private CountDownLatch countDownLatch = new CountDownLatch(1);

    /**
     * 开启连接
     */
    @Before
    public void befor() throws IOException, InterruptedException {
        //创建连接，因为是异步连接的，需要等待连接成功才能使用
        // arg1：连接地址
        // arg2：超时时间
        // arg3：自定义监视器
        zooKeeper = new ZooKeeper(IP, 5000, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                //连接成功
                if(Event.KeeperState.SyncConnected.equals(watchedEvent.getState())){
                    countDownLatch.countDown();
                    System.out.println("连接成功......");
                }else if(Event.KeeperState.Disconnected.equals(watchedEvent.getState())){
                    System.out.println("连接失败......");
                }else if(Event.KeeperState.AuthFailed.equals(watchedEvent.getState())){
                    System.out.println("用户认证失败......");
                }
            }
        });
        //等待连接成功
        countDownLatch.await();
    }

    /**
     * 关闭连接
     * @throws InterruptedException
     */
    @After
    public void after() throws InterruptedException {
        zooKeeper.close();
    }

    /**
     * 同步获取节点数据，并且不开启连接对象的监听器
     */
    @Test
    public void getData1() throws KeeperException, InterruptedException {
        Stat stat = new Stat();
        // arg1：节点路径
        // arg2：是否开启连接对象的监听器 false：不开启，true：开启
        // arg3：节点状态对象
        byte[] data = zooKeeper.getData("/data1", false, stat);
        System.out.println("节点数据：" + new String(data));
        System.out.println("节点版本号：" + stat.getVersion());
    }

    /**
     * 自定义监视器
     * 支持监控的事件
     *  NodeDeleted
     *  NodeDataChanged
     */
    Watcher watcher = new Watcher() {
        @Override
        public void process(WatchedEvent watchedEvent) {
            //节点路径
            System.out.println("节点路径：" + watchedEvent.getPath());
            //事件类型
            System.out.println("事件类型：" + watchedEvent.getType());
        }
    };

    /**
     * 同步获取节点数据，使用自定义监视器，监视节点数据变化
     */
    @Test
    public void getData2() throws KeeperException, InterruptedException {
        Stat stat = new Stat();
        // arg1：节点路径
        // arg2：监听器
        // arg3：节点状态对象
        byte[] data = zooKeeper.getData("/data2", watcher, stat);
        System.out.println("节点数据：" + new String(data));
        System.out.println("节点版本号：" + stat.getVersion());
        Thread.sleep(Long.MAX_VALUE);
        System.out.println("结束");
    }

    /**
     * 自定义实现回调接口
     */
    AsyncCallback.DataCallback dataCallback = new AsyncCallback.DataCallback(){
        @Override
        public void processResult(int i, String s, Object o, byte[] bytes, Stat stat) {
            //结果
            System.out.println("结果：" + i);
            //节点路径
            System.out.println("节点路径：" + s);
            //上下文对象
            System.out.println("上下文对象：" + o);
            //节点数据
            System.out.println("节点数据：" + new String(bytes));
            //节点状态
            System.out.println("节点版本号：" + stat.getVersion());
        }
    };

    /**
     * 异步获取数据，不开启连接对象监视器
     */
    @Test
    public void getData3() throws InterruptedException {
        //arg1：节点路径
        //arg2：是否开启连接对象的监视器
        //arg3：异步获取数据的回调接口实现类
        //arg4：上下文对象
        zooKeeper.getData("/data3",false,dataCallback,"I am context");
        Thread.sleep(Long.MAX_VALUE);
        System.out.println("结束");
    }

    /**
     * 异步获取节点数据，开启自定义监视器
     */
    @Test
    public void getData4() throws InterruptedException {
        //arg1：节点路径
        //arg2：自定义监视器
        //arg3：异步获取数据的回调接口实现类
        //arg4：上下文对象
        zooKeeper.getData("/data4",watcher,dataCallback,"I am context");
        Thread.sleep(Long.MAX_VALUE);
        System.out.println("结束");
    }

    /**************************以下为获取子节点****************************/

    /**
     * 同步获取子节点，并且不开启连接器监控
     */
    @Test
    public void getChildren1() throws KeeperException, InterruptedException {
        //arg1：父节点路径
        //arg2：是否开启连接器监控
        List<String> children = zooKeeper.getChildren("/child", false);
        System.out.println("子节点：" + children);
    }

    /**
     * 自定义监视器
     * 支持监控的事件
     *  NodeChildrenChanged
     */
    Watcher childWatcher = new Watcher() {
        @Override
        public void process(WatchedEvent watchedEvent) {
            //节点路径
            System.out.println("节点路径：" + watchedEvent.getPath());
            //事件类型
            System.out.println("事件类型：" + watchedEvent.getType());
        }
    };

    /**
     * 同步获取子节点，并且开启自定义监听器
     */
    @Test
    public void getChildren2() throws KeeperException, InterruptedException {
        //arg1：父节点路径
        //arg2：自定义监视器
        List<String> children = zooKeeper.getChildren("/child", childWatcher);
        System.out.println("子节点：" + children);
        Thread.sleep(Long.MAX_VALUE);
        System.out.println("结束");
    }

    /**
     * 同步查询子节点，不开启连接器监控
     */
    @Test
    public void getChildren3() throws KeeperException, InterruptedException {
        Stat stat = new Stat();
        //arg1：父节点路径
        //arg2：是否开启连接器监控
        //arg3：父节点状态对象
        List<String> children = zooKeeper.getChildren("/child", false, stat);
        System.out.println("子节点：" + children);
        System.out.println("父节点版本号：" + stat.getVersion());
    }

    /**
     * 同步获取子节点，并且开启自定义监听器
     */
    @Test
    public void getChildren4() throws KeeperException, InterruptedException {
        Stat stat = new Stat();
        //arg1：父节点路径
        //arg2：自定义监视器
        //arg3：父节点状态对象
        List<String> children = zooKeeper.getChildren("/child", childWatcher,stat);
        System.out.println("子节点：" + children);
        System.out.println("父节点版本号：" + stat.getVersion());
        Thread.sleep(Long.MAX_VALUE);
        System.out.println("结束");
    }

    /**
     * 异步获取子节点列表，不开启连接器监控
     */
    @Test
    public void getChildren5() throws InterruptedException {
        zooKeeper.getChildren("/child", false, new AsyncCallback.ChildrenCallback() {
            @Override
            public void processResult(int i, String s, Object o, List<String> list) {
                //结果
                System.out.println("结果：" + i);
                //节点路径
                System.out.println("节点路径：" + s);
                //上下文对象
                System.out.println("上下文对象：" + o);
                //子节点
                System.out.println("子节点：" + list);
            }
        },"I am context");
        Thread.sleep(Long.MAX_VALUE);
        System.out.println("结束");
    }

    /**
     * 异步获取子节点列表，开启自定义连接器监控
     */
    @Test
    public void getChildren6() throws InterruptedException {
        zooKeeper.getChildren("/child", childWatcher, new AsyncCallback.ChildrenCallback() {
            @Override
            public void processResult(int i, String s, Object o, List<String> list) {
                //结果
                System.out.println("结果：" + i);
                //节点路径
                System.out.println("节点路径：" + s);
                //上下文对象
                System.out.println("上下文对象：" + o);
                //子节点
                System.out.println("子节点：" + list);
            }
        },"I am context");
        Thread.sleep(Long.MAX_VALUE);
        System.out.println("结束");
    }

    @Test
    public void getChildren7() throws InterruptedException {
        zooKeeper.getChildren("/child", false, new AsyncCallback.Children2Callback() {
            @Override
            public void processResult(int i, String s, Object o, List<String> list, Stat stat) {
                //结果
                System.out.println("结果：" + i);
                //节点路径
                System.out.println("节点路径：" + s);
                //上下文对象
                System.out.println("上下文对象：" + o);
                //子节点
                System.out.println("子节点：" + list);
                //父节点状态对象
                System.out.println("父节点版本号：" + stat.getVersion());
            }
        },"I am context");
        Thread.sleep(Long.MAX_VALUE);
        System.out.println("结束");
    }

}
